﻿#pragma once

#include "MapObject.h"
#include "../Settings.h"
#include "../../Shared/ClientPackets.h"
#include "../../Shared/Enums.h"
#include "../MirDatabase/CharacterInfo.h"
#include "../MirDatabase/AccountInfo.h"
#include "../MirNetwork/MirConnection.h"
#include "Player/Reporting.h"
#include "NPC/NPCScript.h"
#include "NPC/NPCPage.h"
#include "NPC/NPCSegment.h"
#include "NPCObject.h"
#include "../MirEnvir/Map.h"
#include "../MirDatabase/AuctionInfo.h"
#include "../../Shared/Data/ItemData.h"
#include "GuildObject.h"
#include "../../Shared/Data/GuildData.h"
#include "../MirEnvir/Envir.h"
#include "../MirDatabase/QuestProgressInfo.h"
#include "DelayedAction.h"
#include "../MirDatabase/QuestInfo.h"
#include "../MirDatabase/RecipeInfo.h"
#include "../MirDatabase/MineInfo.h"
#include "../MirDatabase/MagicInfo.h"
#include "MonsterObject.h"
#include "../../Shared/Packet.h"
#include "../../Shared/Data/Stat.h"
#include "../MirDatabase/MonsterInfo.h"
#include <string>
#include <unordered_map>
#include <vector>
#include <algorithm>
#include <cmath>
#include <limits>
#include <any>
#include "exceptionhelper.h"
#include "../../bankersrounding.h"
#include "../../stringhelper.h"
#include "../../tangible_filesystem.h"

using namespace ClientPackets;
using namespace Server::MirDatabase;
using namespace Server::MirEnvir;
using namespace Server::MirNetwork;
namespace S = ServerPackets;
using namespace Server::MirObjects::Monsters;

namespace Server::MirObjects
{
    class PlayerObject final : public MapObject
    {
    private:
        long long NextTradeTime = 0;
        long long NextGroupInviteTime = 0;

    public:
        std::string GMPassword = Settings::GMPassword;
        bool IsGM = false, GMLogin = false, GMNeverDie = false, GMGameMaster = false, EnableGroupRecall = false, EnableGuildInvite = false, AllowMarriage = false, AllowLoverRecall = false, AllowMentor = false, HasMapShout = false, HasServerShout = false; //TODO - Remove

        bool HasUpdatedBaseStats = true;

        long long LastRecallTime = 0, LastRevivalTime = 0, LastTeleportTime = 0, LastProbeTime = 0;
        long long MenteeEXP = 0;

        short TransformType = 0;
        short Looks_Armour = 0, Looks_Weapon = -1, Looks_WeaponEffect = 0;
        unsigned char Looks_Wings = 0;

        bool WarZone = false;

        virtual ~PlayerObject()
        {
            delete Info;
            delete Account;
            delete Connection;
            delete Report;
            delete NPCPage;
            delete NPCMoveMap;
            delete NPCMoveCoord;
            delete ReincarnationTarget;
            delete ReincarnationHost;
            delete MyGuild;
            delete MyGuildRank;
            delete PendingGuildInvite;
            delete MarriageProposal;
            delete DivorceProposal;
            delete MentorRequest;
            delete GroupInvitation;
            delete TradeInvitation;
            delete TradePartner;
            delete ItemRentalPartner;
            delete ItemRentalDepositedItem;
        }

        ObjectType getRace() const override;

        CharacterInfo *Info;
        AccountInfo *Account;
        MirConnection *Connection;
        Reporting *Report;

        std::string getName() const override;
        void setName(const std::string &value) override;

        int getCurrentMapIndex() const override;
        void setCurrentMapIndex(int value) override;
        Point *getCurrentLocation() const override;
        void setCurrentLocation(Point *value) override;
        MirDirection getDirection() const override;
        void setDirection(MirDirection value) override;
        unsigned short getLevel() const override;
        void setLevel(unsigned short value) override;

        int getHealth() const override;

        int getMaxHealth() const override;

        int getHP() const;
        void setHP(int value);

        int getMP() const;
        void setMP(int value);

        AttackMode getAMode() const override;
        void setAMode(AttackMode value) override;
        PetMode getPMode() const override;
        void setPMode(PetMode value) override;

        void setExperience(long long value);
        long long getExperience() const;

        long long MaxExperience = 0;

        bool NewMail = false;

        int getPKPoints() const override;
        void setPKPoints(int value) override;

        unsigned char getHair() const;
        void setHair(unsigned char value);
        MirClass getClass() const;
        MirGender getGender() const;

        int getBindMapIndex() const;
        void setBindMapIndex(int value);
        Point *getBindLocation() const;
        void setBindLocation(Point *value);

        bool RidingMount = false;
        MountInfo *getMount() const;
        short getMountType() const;
        void setMountType(short value);

        int FishingChance = 0, FishingChanceCounter = 0, FishingProgressMax = 0, FishingProgress = 0, FishingAutoReelChance = 0, FishingNibbleChance = 0;
        bool Fishing = false, FishingAutocast = false, FishFound = false, FishFirstFound = false;

        bool getCanMove() const;
        bool getCanWalk() const;
        bool getCanRun() const;
        bool getCanAttack() const;

        bool getCanRegen() const;
    private:
        bool getCanCast() const;

    public:
        static constexpr long long TurnDelay = 350, MoveDelay = 600, HarvestDelay = 350, RegenDelay = 10000, PotDelay = 200, HealDelay = 600, DuraDelay = 10000, VampDelay = 500, LoyaltyDelay = 1000, FishingCastDelay = 750, FishingDelay = 200, ItemExpireDelay = 60000, MovementDelay = 2000;
        long long ActionTime = 0, RunTime = 0, RegenTime = 0, PotTime = 0, HealTime = 0, AttackTime = 0, StruckTime = 0, TorchTime = 0, DuraTime = 0, DecreaseLoyaltyTime = 0, IncreaseLoyaltyTime = 0, ChatTime = 0, ShoutTime = 0, SpellTime = 0, VampTime = 0, SearchTime = 0, FishingTime = 0, LogTime = 0, FishingFoundTime = 0, CreatureTimeLeftTicker = 0, StackingTime = 0, ItemExpireTime = 0, RestedTime = 0, MovementTime = 0;

        unsigned char ChatTick = 0;

        bool HasElemental = false;
        int ElementsLevel = 0;

        bool Stacking = false;

        bool SendIntelligentCreatureUpdates = false;
        IntelligentCreatureType SummonedCreatureType = IntelligentCreatureType::None;
        bool CreatureSummoned = false;

        LevelEffects LevelEffects = LevelEffects::None;

    private:
        int _stepCounter = 0, _runCounter = 0, _fishCounter = 0, _restedCounter = 0;

    public:
        NPCScript *getDefaultNPC() const;

        unsigned int NPCObjectID = 0;
        int NPCScriptID = 0;
        NPCPage *NPCPage;
        std::unordered_map<NPCSegment*, bool> NPCSuccess = std::unordered_map<NPCSegment*, bool>();
        bool NPCDelayed = false;
        std::vector<std::string> NPCSpeech = std::vector<std::string>();
        Map *NPCMoveMap;
        Point *NPCMoveCoord;
        std::string NPCInputStr;

        bool UserMatch = false;
        std::string MatchName;
        ItemType MatchType = static_cast<ItemType>(0);
        MarketPanelType MarketPanelType = static_cast<MarketPanelType>(0);
        short MinShapes = 0, MaxShapes = 0;

        int PageSent = 0;
        std::vector<AuctionInfo*> Search = std::vector<AuctionInfo*>();
        std::vector<ItemSets*> ItemSets = std::vector<ItemSets*>();
        std::vector<EquipmentSlot> MirSet = std::vector<EquipmentSlot>();

        bool FatalSword = false, Slaying = false, TwinDrakeBlade = false, FlamingSword = false, MPEater = false, Hemorrhage = false, CounterAttack = false;
        int MPEaterCount = 0, HemorrhageAttackCount = 0;
        long long FlamingSwordTime = 0, CounterAttackTime = 0;
        bool ActiveBlizzard = false, ActiveReincarnation = false, ActiveSwiftFeet = false, ReincarnationReady = false;
        PlayerObject *ReincarnationTarget, *ReincarnationHost;
        long long ReincarnationExpireTime = 0;

        float HpDrain = 0;

        bool UnlockCurse = false;
        bool FastRun = false;
        bool CanGainExp = true;

        bool CanCreateGuild = false;
        GuildObject *MyGuild = nullptr;
        GuildRank *MyGuildRank = nullptr;
        GuildObject *PendingGuildInvite = nullptr;
        bool GuildNoticeChanged = true; //set to false first time client requests notice list, set to true each time someone in guild edits notice
        bool GuildMembersChanged = true; //same as above but for members
        bool GuildCanRequestItems = true;
        bool RequestedGuildBuffInfo = false;
        bool getBlocking() const override;
        bool getAllowGroup() const;
        void setAllowGroup(bool value);

        bool getAllowTrade() const;
        void setAllowTrade(bool value);

        SpecialItemMode SpecialMode = static_cast<SpecialItemMode>(0);

        PlayerObject *MarriageProposal;
        PlayerObject *DivorceProposal;
        PlayerObject *MentorRequest;

        PlayerObject *GroupInvitation;
        PlayerObject *TradeInvitation;

        PlayerObject *TradePartner = nullptr;
        bool TradeLocked = false;
        unsigned int TradeGoldAmount = 0;

        PlayerObject *ItemRentalPartner = nullptr;
        UserItem *ItemRentalDepositedItem = nullptr;
        unsigned int ItemRentalFeeAmount = 0;
        unsigned int ItemRentalPeriodLength = 0;
        bool ItemRentalFeeLocked = false;
        bool ItemRentalItemLocked = false;

    private:
        long long LastRankUpdate = getEnvir()->getTime();

    public:
        std::vector<QuestProgressInfo*> getCurrentQuests() const;

        std::vector<int> getCompletedQuests() const;

        PlayerObject(CharacterInfo *info, MirConnection *connection);

        void StopGame(unsigned char reason);

    private:
        std::string LogOutReason(unsigned char reason);

        void NewCharacter();

    public:
        long long GetDelayTime(long long original);

        void Process() override;

        void SetOperateTime() override;

    private:
        void ProcessBuffs();
        void ProcessInfiniteBuffs();
        void ProcessRegen();
        void ProcessPoison();
        bool ProcessDelayedExplosion(Poison *poison);

        void ProcessItems();

    public:
        void Process(DelayedAction *action) override;

    private:
        void SetHP(int amount);
        void SetMP(int amount);

    public:
        void ChangeHP(int amount);
        //use this so you can have mobs take no/reduced poison damage
        void PoisonDamage(int amount, MapObject *Attacker);
        void ChangeMP(int amount);
        void Die() override;

    private:
        void DeathDrop(MapObject *killer);
        void RedDeathDrop(MapObject *killer);

    public:
        void WinExp(unsigned int amount, unsigned int targetLevel = 0) override;

        void GainExp(unsigned int amount);

        void LevelUp();

    private:
        static int FreeSpace(std::vector<UserItem*> &array);

        void AddQuestItem(UserItem *item);

        void AddItem(UserItem *item);

        bool CorrectStartItem(ItemInfo *info);
    public:
        void CheckItemInfo(ItemInfo *info, bool dontLoop = false);
        void CheckItem(UserItem *item);
        void CheckQuestInfo(QuestInfo *info);

        void CheckRecipeInfo(RecipeInfo *info);

    private:
        void SetBind();
    public:
        void StartGame();
    private:
        void StartGameSuccess();

        void StartGameFailed();

    public:
        void SetLevelEffects();
        void GiveRestedBonus(int count);

        void Revive(int hp, bool effect);
        void TownRevive();

    private:
        void GetItemInfo();
        void GetUserInfo();
        void GetMapInfo();

        void GetQuestInfo();
        void GetRecipeInfo();
        void GetObjects();
        void GetObjectsPassive();

        #pragma region Refresh Stats

    public:
        void RefreshStats();

    private:
        void RefreshLevelStats();

        void RefreshBagWeight();

        void RefreshEquipmentStats();

        void RefreshSocketStats(UserItem *equipItem, std::vector<std::string> &skillsToAdd);

        void RefreshItemSetStats();

        void RefreshMirSetStats();

    public:
        void RefreshStatCaps();

        #pragma endregion

    private:
        void AddTempSkills(std::vector<std::string> &skillsToAdd);
        void RemoveTempSkills(std::vector<std::string> &skillsToRemove);

        void RefreshSkills();

        void RefreshBuffs();

    public:
        void RefreshGuildBuffs();

        void RefreshNameColour();

        Color *GetNameColour(PlayerObject *player);

        void BroadcastColourChange();

        void BroadcastInfo() override;

        void Chat(const std::string &message, std::vector<ChatItem*> &linkedItems = std::vector<ChatItem>());

    private:
        std::string ProcessChatItems(const std::string &text, std::vector<PlayerObject*> &recipients, std::vector<ChatItem*> &chatItems);

    public:
        void Turn(MirDirection dir);
        void Harvest(MirDirection dir);
        void Walk(MirDirection dir);
        void Run(MirDirection dir);
        int Pushed(MapObject *pusher, MirDirection dir, int distance) override;

        void RangeAttack(MirDirection dir, Point *location, unsigned int targetID);

        void Attack(MirDirection dir, Spell spell);

        void GetMinePayout(MineSet *Mine);

        void Magic(Spell spell, MirDirection dir, unsigned int targetID, Point *location);

        #pragma region Elemental System
    private:
        void Concentration(UserMagic *magic);

    public:
        void UpdateConcentration(bool concentrating, bool interrupted);

    private:
        bool ElementalShot(MapObject *target, UserMagic *magic);

    public:
        void GatherElement();

        void ObtainElement(bool cast);

        int GetElementalOrbCount();
        int GetElementalOrbPower(bool defensive);
        #pragma endregion

        #pragma region Wizard Skills
    private:
        bool Fireball(MapObject *target, UserMagic *magic);
        void Repulsion(UserMagic *magic);
        void ElectricShock(MonsterObject *target, UserMagic *magic);
        void HellFire(UserMagic *magic);
        void ThunderBolt(MapObject *target, UserMagic *magic);
        void Vampirism(MapObject *target, UserMagic *magic);
        void FireBang(UserMagic *magic, Point *location);
        void FireWall(UserMagic *magic, Point *location);
        void Lightning(UserMagic *magic);
        void TurnUndead(MapObject *target, UserMagic *magic);
        void FlameDisruptor(MapObject *target, UserMagic *magic);
        void ThunderStorm(UserMagic *magic);
        void Mirroring(UserMagic *magic);
        void Blizzard(UserMagic *magic, Point *location, bool &cast);
        void MeteorStrike(UserMagic *magic, Point *location, bool &cast);

        void IceThrust(UserMagic *magic);

        void MagicBooster(UserMagic *magic);

        #pragma endregion

        #pragma region Taoist Skills
        void Healing(MapObject *target, UserMagic *magic);
        bool Poisoning(MapObject *target, UserMagic *magic);
        bool SoulFireball(MapObject *target, UserMagic *magic, bool &cast);
        void SummonSkeleton(UserMagic *magic);
        void Purification(MapObject *target, UserMagic *magic);
        void SummonShinsu(UserMagic *magic);
        void Hiding(UserMagic *magic);
        void MassHiding(UserMagic *magic, Point *location, bool &cast);
        void SoulShield(UserMagic *magic, Point *location, bool &cast);
        void MassHealing(UserMagic *magic, Point *location);
        void Revelation(MapObject *target, UserMagic *magic);
        void PoisonCloud(UserMagic *magic, Point *location, bool &cast);
        void TrapHexagon(UserMagic *magic, Point *location, bool &cast);
        void Reincarnation(UserMagic *magic, PlayerObject *target, bool &cast);
        void SummonHolyDeva(UserMagic *magic);
        void Hallucination(MapObject *target, UserMagic *magic);
        void EnergyShield(MapObject *target, UserMagic *magic, bool &cast);
        void UltimateEnhancer(MapObject *target, UserMagic *magic, bool &cast);
        void Plague(UserMagic *magic, Point *location, bool &cast);
        void Curse(UserMagic *magic, Point *location, bool &cast);


        void PetEnhancer(MapObject *target, UserMagic *magic, bool &cast);
        #pragma endregion

        #pragma region Warrior Skills
        void Entrapment(MapObject *target, UserMagic *magic);
        void BladeAvalanche(UserMagic *magic);
        void ProtectionField(UserMagic *magic);
        void Rage(UserMagic *magic);
        void ShoulderDash(UserMagic *magic);
        void SlashingBurst(UserMagic *magic, bool &cast);
        void FurySpell(UserMagic *magic, bool &cast);
        void ImmortalSkin(UserMagic *magic, bool &cast);
        void CounterAttackCast(UserMagic *magic, MapObject *target);
        #pragma endregion

        #pragma region Assassin Skills

        void HeavenlySword(UserMagic *magic);
        void SwiftFeet(UserMagic *magic, bool &cast);
        void MoonLight(UserMagic *magic);
        void Trap(UserMagic *magic, MapObject *target, bool &cast);
        bool PoisonSword(UserMagic *magic);
        void DarkBody(MapObject *target, UserMagic *magic);
        void CrescentSlash(UserMagic *magic);

        void FlashDash(UserMagic *magic);
        #pragma endregion

        #pragma region Archer Skills
        int ApplyArcherState(int damage);

        bool StraightShot(MapObject *target, UserMagic *magic);
        bool DoubleShot(MapObject *target, UserMagic *magic);
        void BackStep(UserMagic *magic);
        bool DelayedExplosion(MapObject *target, UserMagic *magic);
        void ExplosiveTrap(UserMagic *magic, Point *location);

    public:
        void DoKnockback(MapObject *target, UserMagic *magic); //ElementalShot - knockback
        void BindingShot(UserMagic *magic, MapObject *target, bool &cast);
        void SpecialArrowShot(MapObject *target, UserMagic *magic);
        void NapalmShot(MapObject *target, UserMagic *magic);
        void ArcherSummon(UserMagic *magic, MapObject *target, Point *location);

        void OneWithNature(MapObject *target, UserMagic *magic);
        #pragma endregion

        #pragma region Custom
    private:
        void Portal(UserMagic *magic, Point *location, bool &cast);

        bool FireBounce(MapObject *target, UserMagic *magic, MapObject *source, int bounce = -1);

        bool MeteorShower(MapObject *target, UserMagic *magic);

        #pragma endregion

        void CheckSneakRadius();

        void CompleteMagic(std::vector<std::any> &data);

        void CompleteMine(std::vector<std::any> &data);
        void CompleteAttack(std::vector<std::any> &data);
        void CompleteDamageIndicator(std::vector<std::any> &data);

        void CompleteNPC(std::vector<std::any> &data);
        void CompletePoison(std::vector<std::any> &data);

        UserItem *GetAmulet(int count, int shape = 0);
        UserItem *GetPoison(int count, unsigned char shape = 0);
        UserItem *GetBait(int count);

        UserItem *GetFishingItem(FishingSlot type);
        void DeleteFishingItem(FishingSlot type);
        void DamagedFishingItem(FishingSlot type, int lossDura);

    public:
        UserMagic *GetMagic(Spell spell);

        void LevelMagic(UserMagic *magic);

        bool CheckMovement(Point *location);
    private:
        void CompleteMapMovement(std::vector<std::any> &data);

    public:
        bool Teleport(Map *temp, Point *location, bool effects = true, unsigned char effectnumber = 0) override;
        bool TeleportEscape(int attempts);

    private:
        Packet *GetMountInfo();
        Packet *GetUpdateInfo();

    public:
        Packet *GetInfo() override;
        Packet *GetInfoEx(PlayerObject *player);

        bool IsAttackTarget(PlayerObject *attacker) override;
        bool IsAttackTarget(MonsterObject *attacker) override;
        bool IsFriendlyTarget(PlayerObject *ally) override;
        bool IsFriendlyTarget(MonsterObject *ally) override;
        int Attacked(PlayerObject *attacker, int damage, DefenceType type = DefenceType::ACAgility, bool damageWeapon = true) override;
        int Attacked(MonsterObject *attacker, int damage, DefenceType type = DefenceType::ACAgility) override;
        int Struck(int damage, DefenceType type = DefenceType::ACAgility) override;
        void ApplyPoison(Poison *p, MapObject *Caster = nullptr, bool NoResist = false, bool ignoreDefence = true) override;

        Buff *AddBuff(BuffType type, MapObject *owner, int duration, Stats *stat, bool visible = false, bool infinite = false, bool stackable = false, bool refreshStats = true, std::vector<int> &values) override;

        void PauseBuff(Buff *b);
        void UnpauseBuff(Buff *b);

        void EquipSlotItem(MirGridType grid, unsigned long long id, int to, MirGridType gridTo, unsigned long long idTo);
        void RemoveItem(MirGridType grid, unsigned long long id, int to);
        void RemoveSlotItem(MirGridType grid, unsigned long long id, int to, MirGridType gridTo, unsigned long long idFrom);
        void MoveItem(MirGridType grid, int from, int to);
        void StoreItem(int from, int to);
        void TakeBackItem(int from, int to);
        void EquipItem(MirGridType grid, unsigned long long id, int to);
        void UseItem(unsigned long long id);
        void SplitItem(MirGridType grid, unsigned long long id, unsigned short count);

        void MergeItem(MirGridType gridFrom, MirGridType gridTo, unsigned long long fromID, unsigned long long toID);
        void CombineItem(unsigned long long fromID, unsigned long long toID);
    private:
        bool ValidGemForItem(UserItem *Gem, unsigned char itemtype);
        //Gems granting multiple stat types are not compatiable with this method.
        Stat GetGemType(UserItem *gem);

        //Gems granting multiple stat types are not compatible with this method.
        int GetCurrentStatCount(UserItem *gem, UserItem *item);
    public:
        void DropItem(unsigned long long id, unsigned short count);
        void DropGold(unsigned int gold);
        void PickUp();

    private:
        bool IsGroupMember(MapObject *player);

    public:
        bool CanGainGold(unsigned int gold) override;
        void WinGold(unsigned int gold) override;
        void GainGold(unsigned int gold);
        void GainCredit(unsigned int credit);

        bool CanGainItem(UserItem *item, bool useWeight = true);
        bool CanGainItems(std::vector<UserItem*> &items);

        void GainItem(UserItem *item);
        void GainItemMail(UserItem *item, int reason);

    private:
        bool DropItem(UserItem *item, int range = 1, bool DeathDrop = false);
        bool CanUseItem(UserItem *item);
        bool CanEquipItem(UserItem *item, int slot);
    public:
        bool CanRemoveItem(MirGridType grid, UserItem *item);

        bool CheckQuestItem(UserItem *uItem, unsigned short count);
        bool CanGainQuestItem(UserItem *item);
        void GainQuestItem(UserItem *item);

        void TakeQuestItem(ItemInfo *uItem, unsigned short count);

    private:
        void DamageDura();
    public:
        void DamageWeapon();
        void DamageItem(UserItem *item, int amount, bool isChanged = false);
    private:
        void ConsumeItem(UserItem *item, unsigned char cost);

        bool TryLuckWeapon();

    public:
        void RequestChatItem(unsigned long long id);
        void Inspect(unsigned int id);
        void Inspect(int id);
        void RemoveObjects(MirDirection dir, int count);
        void AddObjects(MirDirection dir, int count);
        void Remove(PlayerObject *player) override;
        void Add(PlayerObject *player) override;
        void Remove(MonsterObject *monster) override;
        void Add(MonsterObject *monster) override;
        void SendHealth(PlayerObject *player) override;

        void ReceiveChat(const std::string &text, ChatType type) override;

        void ReceiveOutputMessage(const std::string &text, OutputMessageType type);

    private:
        void CleanUp();

    public:
        void Enqueue(Packet *p);

        void SpellToggle(Spell spell, bool use);

    private:
        void ShowMentalState();

        void UpdateGMBuff();

    public:
        void Opendoor(unsigned char Doorindex);


        #pragma region NPC

        void CallDefaultNPC(DefaultNPCType type, std::vector<std::any> &value);

        void CallDefaultNPC(const std::string &key);

        void CallNPC(unsigned int objectID, const std::string &key);
    private:
        void CallNPCNextPage();

    public:
        void BuyItem(unsigned long long index, unsigned short count, PanelType type);
        void CraftItem(unsigned long long index, unsigned short count, std::vector<int> &slots);


        void SellItem(unsigned long long uniqueID, unsigned short count);
        void RepairItem(unsigned long long uniqueID, bool special = false);
        void SendStorage();

        #pragma endregion

        #pragma region Consignment
        void ConsignItem(unsigned long long uniqueID, unsigned int price, MarketPanelType panelType);

    private:
        bool Match(AuctionInfo *info);

    public:
        void MarketPage(int page);

        void GetMarket(const std::string &name, ItemType type);

        void MarketSearch(const std::string &match, ItemType type);

        void MarketBuy(unsigned long long auctionID, unsigned int bidPrice = 0);

        void MarketSellNow(unsigned long long auctionID);

        void MarketGetBack(unsigned long long auctionID);

        void RequestUserName(unsigned int id);

        #pragma endregion

        #pragma region Awakening

        void Awakening(unsigned long long UniqueID, AwakeType type);

        void DowngradeAwakening(unsigned long long UniqueID);

        void DisassembleItem(unsigned long long UniqueID);

        void ResetAddedItem(unsigned long long UniqueID);

        void AwakeningNeedMaterials(unsigned long long UniqueID, AwakeType type);

        void AwakeningEffect(bool isSuccess, std::vector<bool> &isHit);

        bool HasAwakeningNeedMaterials(UserItem *item, AwakeType type);

        #pragma endregion

        #pragma region Groups

        void SwitchGroup(bool allow);

        void RemoveGroupBuff();
        void AddMember(const std::string &name);
        void DelMember(const std::string &name);
        void GroupInvite(bool accept);

        #pragma endregion

        #pragma region Guilds

        void CreateNewbieGuild(const std::string &GuildName);
        bool CreateGuild(const std::string &GuildName);
        void EditGuildMember(const std::string &Name, const std::string &RankName, unsigned char RankIndex, unsigned char ChangeType);
        void EditGuildNotice(std::vector<std::string> &notice);
        void GuildInvite(bool accept);
        void RequestGuildInfo(unsigned char Type);
        void GuildNameReturn(const std::string &Name);
        void GuildStorageGoldChange(unsigned char Type, unsigned int Amount);
        void GuildStorageItemChange(unsigned char Type, int from, int to);
        void GuildWarReturn(const std::string &Name);

        bool AtWar(PlayerObject *attacker);

        void GuildBuffUpdate(unsigned char Type, int Id);

        #pragma endregion

        #pragma region Trading

        void DepositTradeItem(int from, int to);
        void RetrieveTradeItem(int from, int to);



        void TradeRequest();
        void TradeReply(bool accept);
        void TradeGold(unsigned int amount);
        void TradeItem();

        void TradeUnlock();

        void TradeConfirm(bool confirm);
        void TradeCancel();

        #pragma endregion

        #pragma region Mounts

        void RefreshMount(bool refreshStats = true);
        void IncreaseMountLoyalty(int amount);
        void DecreaseMountLoyalty(int amount);

        #pragma endregion

        #pragma region Fishing

        void FishingCast(bool cast, bool cancel = false);
        void FishingChangeAutocast(bool autoCast);
        void UpdateFish();
    private:
        Packet *GetFishInfo();

        #pragma endregion

        #pragma region Quests

    public:
        void AcceptQuest(int index);

        void FinishQuest(int questIndex, int selectedItemIndex = -1);
        void AbandonQuest(int questIndex);
        void ShareQuest(int questIndex);

        void CheckGroupQuestKill(MonsterInfo *mInfo);
        bool CheckGroupQuestItem(UserItem *item, bool gainItem = true);

        bool CheckNeedQuestItem(UserItem *item, bool gainItem = true);
            private:
                return *true;
    };

        private:
            return *false;
}
    public:
        bool CheckNeedQuestFlag(int flagNumber);

        private:
            return *false;
        }
    public:
        void CheckNeedQuestKill(MonsterInfo *mInfo);
        }

        void RecalculateQuestBag();

        void SendUpdateQuest(QuestProgressInfo *quest, QuestState state, bool trackQuest = false);

        void GetCompletedQuests();

        #pragma endregion

        #pragma region Mail

        void SendMail(const std::string &name, const std::string &message);

        void SendMail(const std::string &name, const std::string &message, unsigned int gold, std::vector<unsigned long long> &items, bool stamped);

        void ReadMail(unsigned long long mailID);

        void CollectMail(unsigned long long mailID);

        void DeleteMail(unsigned long long mailID);

        void LockMail(unsigned long long mailID, bool lockMail);

        unsigned int GetMailCost(std::vector<unsigned long long> &items, unsigned int gold, bool stamped);

        void GetMail();

        int GetMailAwaitingCollectionAmount();

        #pragma endregion

        #pragma region IntelligentCreatures

        void SummonIntelligentCreature(IntelligentCreatureType pType);

        void UnSummonIntelligentCreature(IntelligentCreatureType pType, bool doUpdate = true);

        void ReleaseIntelligentCreature(IntelligentCreatureType pType, bool doUpdate = true);

        void UpdateSummonedCreature(IntelligentCreatureType pType);

        void RefreshCreaturesTimeLeft();

        void RefreshCreatureSummoned();

        void IntelligentCreaturePickup(bool mousemode, Point *atlocation);

        void IntelligentCreatureGainPearls(int amount);

        void IntelligentCreatureLosePearls(int amount);

        void IntelligentCreatureProducePearl();
        bool IntelligentCreatureProduceBlackStone();

        void IntelligentCreatureSay(IntelligentCreatureType pType, const std::string &message);

        void StrongboxRewardItem(int boxtype);

        void BlackstoneRewardItem();

    private:
        UserItem *CreateDynamicWonderDrug(int boxtype, UserItem *dropitem);

        IntelligentCreatureObject *GetCreatureByName(const std::string &creaturename);

        std::string CreateTimeString(double secs);

        void GetCreaturesInfo();


        #pragma endregion

        #pragma region Friends

    public:
        void AddFriend(const std::string &name, bool blocked = false);

        void RemoveFriend(int index);

        void AddMemo(int index, const std::string &memo);

        void GetFriends();

        #pragma endregion

        #pragma region Refining

        void DepositRefineItem(int from, int to);
        void RetrieveRefineItem(int from, int to);
        void RefineCancel();
        void RefineItem(unsigned long long uniqueID);
        void CollectRefine();
        void CheckRefine(unsigned long long uniqueID);

        #pragma endregion

        #pragma region Relationship

        void NPCDivorce();

        bool CheckMakeWeddingRing();

        void MakeWeddingRing();

        void ReplaceWeddingRing(unsigned long long uniqueID);

        void MarriageRequest();

        void MarriageReply(bool accept);

        void DivorceRequest();

        void DivorceReply(bool accept);

        void GetRelationship(bool CheckOnline = true);
        void LogoutRelationship();

        #pragma endregion

        #pragma region Mentorship

        void MentorBreak(bool Force = false);

        void AddMentor(const std::string &Name);

        void MentorReply(bool accept);

        void GetMentor(bool CheckOnline = true);

        void LogoutMentor();

        #pragma endregion

        #pragma region Gameshop

        void GameShopStock(GameShopItem *item);

        void GameshopBuy(int GIndex, unsigned char Quantity);

        void GetGameShop();

        #pragma endregion

        #pragma region ConquestWall
        void CheckConquest(bool checkPalace = false);
        void EnterSabuk();

        void LeaveSabuk();
        #pragma endregion

        #pragma region Ranking

    private:
        std::vector<long long> LastRankRequest = std::vector<long long>(6);
    public:
        void GetRanking(unsigned char RankType);

        #pragma endregion

        #pragma region Rental

        void GetRentedItems();

        void ItemRentalRequest();

        void SetItemRentalFee(unsigned int amount);

        void SetItemRentalPeriodLength(unsigned int days);

        void DepositRentalItem(int from, int to);

        void RetrieveRentalItem(int from, int to);

    private:
        void UpdateRentalItem();

    public:
        void CancelItemRental();

        void ItemRentalLockFee();

        void ItemRentalLockItem();

    private:
        void ItemRentalRemoveLocks();

    public:
        void ConfirmItemRental();

        #pragma endregion


        void SetTimer(const std::string &key, int seconds, unsigned char type = 0);

        void ExpireTimer(const std::string &key);
    }
}

